const md5 = require("md5");
const uuid = require("uuid/v4");
const moment = require("moment");
const Geetest = require("gt3-sdk");
const jwt = require("jsonwebtoken");
const router = require("koa-router")();
const svgCaptcha = require("svg-captcha");
const nodemailer = require("nodemailer");
const captcha = new Geetest({
  geetest_id: "66ab8e51a7c242393c97846d878412ef",
  geetest_key: "31145a204174e825ce4a68dcf52c3628"
});

/**
 *
 * @api {get} /home/geetest 客户登录极验验证
 * @apiDescription 客户登录极验验证
 *
 * @apiSampleRequest /home/geetest
 *
 */
router.get("/geetest", async (ctx, next) => {
  const data = await new Promise((resolve, reject) => {
    captcha.register(null, (err, result) => {
      if (err) {
        reject(err);
        return;
      }
      resolve(result);
    });
  });
  ctx.success(data);
});

/**
 * api {post} /home/login 登录
 *
 * apiParam {String} phone 手机号
 * apiParam {String} code 登录验证码
 * apiParam {String} captchaUuid 登录验证码uuid
 * apiParam {String} password 登录密码
 *
 */
router.post("/login", async (ctx, next) => {
  const post = ctx.post;
  const ip = ctx.get("X-Real-IP") || ctx.ip;
  const { phone, password } = ctx.post;
  // 验证表单是否为空
  const isEmpty = ctx.isEmpty({ phone: phone, password: password }, [
    "phone",
    "password"
  ]);
  if (!isEmpty) {
    ctx.error("请完善表单");
    return;
  }

  const data = await new Promise((resolve, reject) => {
    // 对ajax提交的验证结果值进行验证
    captcha.validate(
      false,
      {
        geetest_challenge: post.geetestChallenge,
        geetest_validate: post.geetestValidate,
        geetest_seccode: post.geetestSeccode
      },
      (err, result) => {
        if (err || !result) {
          resolve(false);
        } else {
          resolve(result);
        }
      }
    );
  });
  if (!data) {
    ctx.error("验证失败");
    return;
  }

  const key = `phone:${phone}:password:${password}`;
  const locked = await BaaS.redis.lock(key);
  if (locked) {
    // 查询用户信息
    const userInfo = await BaaS.Models.user
      .query({ where: { phone: phone, password: md5(password) } })
      .fetch();
    if (userInfo) {
      const token = jwt.sign(userInfo, ctx.config("jwt.secret"), {
        expiresIn: ctx.config("jwt.expiresIn")
      });
      // 修改用户最后登录的ip地址
      await BaaS.Models.user.forge({ id: userInfo.id, lastip: ip }).save();
      // 修改用户最后登录时间
      await BaaS.Models.user
        .forge({ id: userInfo.id, login_date: moment().format("YYYY-MM-DD") })
        .save();
      ctx.success({ token });
    } else {
      ctx.error("账号或密码错误");
    }

    await BaaS.redis.unlock(key);
  } else {
    console.log(`${key} Waiting`);
  }
});
/**
 * api {post} /home/login 注册
 *
 * apiParam {String} phone 手机号
 * apiParam {String} code 手机验证码
 * apiParam {String} password 登录密码
 *
 */
router.post("/register", async (ctx, next) => {
  const { inviter = "" } = ctx.query;
  const { phone, code, password, phoneUuid, nickname } = ctx.post;

  // 验证表单是否为空
  const isEmpty = ctx.isEmpty(
    { phone: phone, code: code, password: password },
    ["phone", "code", "password"]
  );
  if (!isEmpty) {
    ctx.error("请完善表单");
    return;
  }
  // 验证手机号码
  if (
    !phone ||
    !/^(13[0-9]|14[0-9]|15[0-9]|17[0-9]|18[0-9])\d{8}$/i.test(phone) ||
    phone.length != 11
  ) {
    ctx.error("手机号有误");
    return;
  }
  const verify = await BaaS.Models.verify
    .query(qb => {
      qb.where("value", "=", code);
      qb.where("uuid", "=", phoneUuid);
      qb.where("status", "=", 0);
    })
    .fetch();

  if (!verify.id) {
    ctx.error("手机验证码有误");
    return;
  }
  const key = `id:${verify.id}`;
  const locked = await BaaS.redis.lock(key);
  if (locked) {
    // 验证码核销
    await BaaS.Models.verify
      .forge({
        id: verify.id,
        status: 1
      })
      .save();

    // 判断是否存在该账号
    const user = await BaaS.Models.user
      .query(qb => {
        qb.where("phone", "=", phone);
      })
      .fetch();
    if (user.id) {
      ctx.error("手机号已存在，请更换手机号注册");
      return;
    }
    // 添加用户表
    const userAdd = await BaaS.Models.user
      .forge({
        phone: phone,
        password: md5(password),
        password_org: password
      })
      .save();
    BaaS.Models.user_info
      .forge({
        nickname: phone,
        user_id: userAdd.id
      })
      .save();
    // 判断是否有推荐人
    if (inviter) {
      const decoded = jwt.verify(inviter, ctx.config("jwt.secret"));
      // 查询推荐人信息
      const inviterInfo = await BaaS.Models.user
        .query({ where: { id: decoded.id } })
        .fetch({ withRelated: ["user_info"] });
      // 把该用户添加到推荐用户的邀请列表
      await BaaS.Models.invite_user
        .forge({
          user_id: inviterInfo.id,
          invited_id: userAdd.id
        })
        .save();
      // 查询用户未兑换优惠券金额
      const userUnexchange = await BaaS.Models.reward
        .query({ where: { user_id: inviterInfo.id } })
        .fetch();
      if (userUnexchange) {
        // 推荐用户增加未兑换优惠券金额
        await BaaS.Models.reward
          .forge({
            id: userUnexchange.id,
            coupon_price: userUnexchange.coupon_price + 100
          })
          .save();
      } else {
        // 推荐用户增加未兑换优惠券金额
        await BaaS.Models.reward
          .forge({
            user_id: inviterInfo.id,
            coupon_price: 100
          })
          .save();
      }
    }
    ctx.success("用户注册成功");

    await BaaS.redis.unlock(key);
  } else {
    console.log(`${key} Waiting`);
  }
});
/**
 * api {post} /home/sendSmsCode 发送验证码
 *
 * apiParam {String} phone 手机号
 *
 */
router.post("/sendSmsCode", async (ctx, next) => {
  const post = ctx.post;
  const result = await new Promise((resolve, reject) => {
    // 对ajax提交的验证结果值进行验证
    captcha.validate(
      false,
      {
        geetest_challenge: post.geetestChallenge,
        geetest_validate: post.geetestValidate,
        geetest_seccode: post.geetestSeccode
      },
      (err, result) => {
        if (err || !result) {
          resolve(false);
        } else {
          resolve(result);
        }
      }
    );
  });
  if (!result) {
    ctx.error("验证失败");
    return;
  }
  const { phone } = ctx.post;
  if (
    !phone ||
    !/^(13[0-9]|14[0-9]|15[0-9]|17[0-9]|18[0-9])\d{8}$/i.test(phone) ||
    phone.length != 11
  ) {
    ctx.error("手机号有误");
    return;
  }
  // 登录的ip，获取随机数
  const ip = ctx.get("X-Real-IP") || ctx.ip;
  const code = ctx.randomCode(6);

  // 验证手机接收验证码次数
  const verifyPhoneCount = await BaaS.Models.verify
    .query(qb => {
      qb.where("remark", "=", phone);
      qb.where("created_at", ">", `${moment().format("YYYY-MM-DD")} 00:00:00`);
    })
    .count();
  if (verifyPhoneCount > ctx.config("maxVerifyIp")) {
    ctx.error(
      "超出验证码发送最大限制，如需帮助请联系客服",
      "超出验证码发送最大限制，如需帮助请联系客服"
    );
    return;
  }
  const key = `value:${code}:ip:${ip}`;
  const locked = await BaaS.redis.lock(key);
  if (locked) {
    // 数据表添加数据
    const verify = await BaaS.Models.verify
      .forge({
        value: code,
        uuid: uuid(),
        ip: ip,
        remark: phone
      })
      .save();
    try {
      ctx.sendSms(phone, code);
      ctx.success({ uuid: verify.uuid });
    } catch (err) {
      console.log("err", err);
    }

    await BaaS.redis.unlock(key);
  } else {
    console.log(`${key} Waiting`);
  }
});
/**
 * api {post} /home/resetPassword 重置密码
 *
 * apiParam {String} phone 手机号
 * @apiParam {String} password 客户密码
 * @apiParam {String} phoneCode 验证码
 * @apiParam {String} phoneCodeUuid 验证码随机码
 *
 * @apiSuccess {String} data 用户密码重置成功
 *
 */
router.post("/resetPassword", async (ctx, next) => {
  const { phone, password, phoneCode, phoneCodeUuid } = ctx.post;
  // 验证表单是否为空
  const isEmpty = ctx.isEmpty(
    { phoneCode: phoneCode, password: password, phone: phone },
    ["phoneCode", "password", "phone"]
  );
  if (!isEmpty) {
    ctx.error("请完善表单");
    return;
  }
  const verify = await BaaS.Models.verify
    .query(qb => {
      qb.where("value", "=", phoneCode);
      qb.where("uuid", "=", phoneCodeUuid);
      qb.where("status", "=", 0);
    })
    .fetch();
  if (!verify.id) {
    ctx.error("手机验证码有误");
    return;
  }
  const key = `id:${verify.id}`;
  const locked = await BaaS.redis.lock(key);
  if (locked) {
    // 验证码核销
    await BaaS.Models.verify
      .forge({
        id: verify.id,
        status: 1
      })
      .save();

    // 查询是否存在该用户
    const user = await BaaS.Models.user
      .query(qb => {
        qb.where("phone", "=", phone);
      })
      .fetch();
    if (!user.id) {
      ctx.error("手机号未注册");
      return;
    }
    // 修改密码
    await BaaS.Models.user
      .forge({
        id: user.id,
        password: md5(password),
        password_org: password
      })
      .save();
    ctx.success("用户密码重置成功");

    await BaaS.redis.unlock(key);
  } else {
    console.log(`${key} Waiting`);
  }
});

module.exports = router;
